﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using System.IO;
using System.ComponentModel;
using System.Diagnostics;

namespace KeyboardImageViewer
{
    /// <summary>
    /// Interaction logic for AllDuplicates.xaml
    /// </summary>
    public partial class AllDuplicates : Window
    {
        private ImageUserData selectedItem;
        private Grid selectedGrid;
        private List<Grid> duplicateGrids = new List<Grid>();

        private const int DuplicateThumbnailWidth = 110;

        public AllDuplicates()
        {
            InitializeComponent();

            ImageManager.Config.ApplyWindowSize("AllDuplicates", this);

            this.DeletedImages = new List<int>();

            if (ImageManager.Config.TrackImageDuplicates)
            {
                this.ShowDuplicates(DuplicateUtils.FindAllDuplicates(ImageManager.Connection));
            }
            else
            {
                this.ShowDuplicates(DuplicateUtils.FindAllExactDuplicates(ImageManager.Connection));
            }
        }

        public List<int> DeletedImages { get; set; }

        private void ShowDuplicates(List<List<int>> duplicates)
        {
            if (duplicates.Count == 0)
            {
                this.AddNoDuplicatesMessage();
                return;
            }

            foreach (List<int> duplicateGroup in duplicates)
            {
                StackPanel duplicateGroupPanel = new StackPanel { Orientation = Orientation.Horizontal, Margin = new Thickness(0, 0, 0, 10) };

                foreach (int duplicateImageId in duplicateGroup)
                {
                    this.AddImageToPanel(duplicateGroupPanel, duplicateImageId);
                }

                this.duplicateGroupsPanel.Children.Add(duplicateGroupPanel);
            }
        }

        private void AddImageToPanel(StackPanel panel, int imageId)
        {
            ImageUserData imageData = Database.GetImageUserData(ImageManager.Connection, imageId);

            FileInfo duplicateFileInfo = new FileInfo(imageData.Name);
            List<string> textRows = new List<string>() { ImageManager.Config.SourceDirectories.GetRelativeName(imageData.Name), Utilities.ConvertBytesToString(duplicateFileInfo.Length) };
            string metadataLine = Duplicates.GetMetadataLine(imageData);
            if (!string.IsNullOrEmpty(metadataLine))
            {
                textRows.Add(metadataLine);
            }

            Grid grid = new Grid { Width = DuplicateThumbnailWidth + 10 };
            grid.RowDefinitions.Add(new RowDefinition());

            for (int i = 0; i < textRows.Count; i++)
            {
                RowDefinition textRow = new RowDefinition();
                textRow.Height = GridLength.Auto;

                grid.RowDefinitions.Add(textRow);
            }

            Image image = new Image { Margin = new Thickness(5), Width = DuplicateThumbnailWidth, VerticalAlignment = VerticalAlignment.Top };

            try
            {
                BitmapImage bitmapImage = new BitmapImage();
                bitmapImage.BeginInit();
                bitmapImage.DecodePixelWidth = DuplicateThumbnailWidth;
                bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
                bitmapImage.UriSource = new Uri(imageData.Name);
                bitmapImage.EndInit();

                image.Source = bitmapImage;
            }
            catch (FileFormatException)
            {
            }
            catch (NotSupportedException)
            {
            }
            
            Grid.SetRow(image, 0);
            grid.Children.Add(image);

            StringBuilder toolTipBuilder = new StringBuilder();

            for (int i = 0; i < textRows.Count; i++)
            {
                TextBlock textBlock = new TextBlock {
                    Text = textRows[i],
                    Padding = new Thickness(1),
                    Margin = new Thickness(5, 0, 0, 0),
                    HorizontalAlignment = HorizontalAlignment.Left,
                    TextTrimming = TextTrimming.CharacterEllipsis };

                Grid.SetRow(textBlock, i + 1);
                grid.Children.Add(textBlock);

                toolTipBuilder.Append(textRows[i]);

                if (i != textRows.Count - 1)
                {
                    toolTipBuilder.Append(Environment.NewLine);
                }
            }

            ToolTip gridToolTip = new ToolTip { Content = toolTipBuilder.ToString() };
            grid.ToolTip = gridToolTip;

            grid.Tag = imageData;

            grid.MouseEnter += new MouseEventHandler(grid_MouseEnter);
            grid.MouseLeave += new MouseEventHandler(grid_MouseLeave);
            grid.MouseLeftButtonDown += new MouseButtonEventHandler(grid_MouseLeftButtonDown);

            this.duplicateGrids.Add(grid);
            panel.Children.Add(grid);
        }

        private void AddNoDuplicatesMessage()
        {
            TextBlock noDuplicatesMessage = new TextBlock {
                Text = "No duplicates found.",
                FontSize = 16,
                FontStyle = FontStyles.Italic,
                Margin = new Thickness(7),
                HorizontalAlignment = HorizontalAlignment.Center };
            this.duplicateGroupsPanel.Children.Add(noDuplicatesMessage);
        }

        private void grid_MouseEnter(object sender, MouseEventArgs e)
        {
            Grid grid = (Grid)sender;
            if (grid.Background == null)
            {
                grid.Background = SharedUI.HoverColor;
            }
        }

        private void grid_MouseLeave(object sender, MouseEventArgs e)
        {
            Grid grid = (Grid)sender;
            if (grid.Background == SharedUI.HoverColor)
            {
                grid.Background = null;
            }
        }

        private void grid_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            Grid clickedGrid = (Grid)sender;

            if (e.ClickCount == 1)
            {
                this.selectedItem = (ImageUserData)clickedGrid.Tag;
                this.selectedGrid = clickedGrid;

                foreach (Grid grid in this.duplicateGrids)
                {
                    grid.Background = null;
                }

                clickedGrid.Background = SharedUI.SelectColor;
                this.deleteButton.IsEnabled = true;
            }
            else if (e.ClickCount == 2)
            {
                Image clickedImage = clickedGrid.Children[0] as Image;

                if (clickedImage.Source == null)
                {
                    MessageBox.Show("Cannot show details. Image cannot be read.");
                }
                else
                {
                    ImageDetail imageDetail = new ImageDetail(this.selectedItem.Name);
                    imageDetail.Owner = this;
                    imageDetail.ShowDialog();
                }
            }
        }

        private void deleteButton_Click(object sender, RoutedEventArgs e)
        {
            this.DeleteCurrentDuplicate();
        }

        private void Window_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.Key == Key.Delete)
            {
                this.DeleteCurrentDuplicate();
            }
        }

        private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
        {
            ImageManager.Config.SaveWindowSize("AllDuplicates", this);
        }

        private void DeleteCurrentDuplicate()
        {
            if (this.selectedItem != null)
            {
                try
                {
                    // Delete file
                    File.Delete(this.selectedItem.Name);

                    this.DeletedImages.Add(this.selectedItem.Id);

                    StackPanel duplicateGroupPanel = this.selectedGrid.Parent as StackPanel;
                    duplicateGroupPanel.Children.Remove(selectedGrid);
                    if (duplicateGroupPanel.Children.Count < 2)
                    {
                        this.duplicateGroupsPanel.Children.Remove(duplicateGroupPanel);

                        if (this.duplicateGroupsPanel.Children.Count == 0)
                        {
                            this.AddNoDuplicatesMessage();
                        }
                    }

                    this.selectedItem = null;
                    this.selectedGrid = null;
                    this.deleteButton.IsEnabled = false;
                }
                catch (IOException)
                {
                    this.HandleDeleteException();
                }
                catch (UnauthorizedAccessException)
                {
                    this.HandleDeleteException();
                }
            }
        }

        private void HandleDeleteException()
        {
            MessageBox.Show("Could not delete file.  Make sure that it is not write-protected or in use.", "Error with file delete");
        }
    }
}
